﻿using GalaSoft.MvvmLight;
using System.Linq;
using System.Collections.ObjectModel;
using JiveMessenger.Models;
using GalaSoft.MvvmLight.Command;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System;
using System.Windows;
using GalaSoft.MvvmLight.Messaging;
using JiveMessenger.User;
using GalaSoft.MvvmLight.Ioc;
using JiveMessenger.Utilities;
using NLog;
using JmShared;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace JiveMessenger.ViewModels
{
    /// <summary>
    /// This class contains properties that a View can data bind to.
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class ViewModelGetUserEmoticons : ViewModelBase
    {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
        private IClient _currentClient;
        public RelayCommand AddEmoticonsCommand { get; set; }
        public RelayCommand<AddUserEmoticonModel> ShortcutChangedCommand { get; set; }
        public RelayCommand<bool> CheckUncheckAllCommand { get; set; }
        public ObservableCollection<IContact> ClientList { get; set; }
        private ObservableCollection<AddUserEmoticonModel> _emoticonList;
        public ObservableCollection<AddUserEmoticonModel> EmoticonList
        {
            get { return _emoticonList; }
            set
            {
                if (_emoticonList != value)
                {
                    _emoticonList = value;
                    RaisePropertyChanged("EmoticonList");
                }
            }
        }



        private bool _isAddButtonEnabled;
        public bool IsAddButtonEnabled
        {
            get { return _isAddButtonEnabled; }
            set
            {
                if (_isAddButtonEnabled != value)
                {
                    _isAddButtonEnabled = value;
                    RaisePropertyChanged("IsAddButtonEnabled");
                }
            }
        }

        //private string _selectedUserId;
        //public string SelectedUserID
        //{
        //    get { return _selectedUserId; }
        //    set
        //    {
        //        if (_selectedUserId != value)
        //        {
        //            _selectedUserId = value;
        //            RaisePropertyChanged("SelectedUserID");
        //            CreateEmoticonListForUser(_selectedUserId);
        //        }
        //    }
        //}

        private IContact _selectedUser;
        public IContact SelectedUser
        {
            get { return _selectedUser; }
            set
            {
                if (_selectedUser != value)
                {
                    _selectedUser = value;
                    RaisePropertyChanged("SelectedUser");

                    Task.Factory.StartNew(() =>
                        {

                            var emoticonList = CreateEmoticonListForUser(_selectedUser.UserID);
                            Application.Current.Dispatcher.BeginInvoke(() =>
                            {
                                if (emoticonList.Count > 0)
                                {
                                    IsAddButtonEnabled = true;
                                }
                                EmoticonList = emoticonList;
                            });
                        });
                }
            }
        }

        ~ViewModelGetUserEmoticons()
        {
            Logger.Debug("ViewModelGetUserEmoticons destructed");
        }

        /// <summary>
        /// Initializes a new instance of the ViewModelGetUserEmoticons class.
        /// </summary>
        public ViewModelGetUserEmoticons(IClient currentClient)
        {
            _currentClient = currentClient;
            IsAddButtonEnabled = false;
            EmoticonList = new ObservableCollection<AddUserEmoticonModel>();
            ClientList = new ObservableCollection<IContact>();
            AddEmoticonsCommand = new RelayCommand(AddEmoticonsCommandAction);
            ShortcutChangedCommand = new RelayCommand<AddUserEmoticonModel>(ShortcutChangedCommandAction);
            CheckUncheckAllCommand = new RelayCommand<bool>(CheckUncheckAllCommandAction);
            Messenger.Default.Send(new NotificationMessageAction<IEnumerable<IContact>>(this, ViewModelContactList.MessengerCommands.GetContacts.ToString(), contacts =>
                {
                   // foreach (UserInfo user in currentClient.ContactClients.Values.GroupBy(user => user.UserName).Select(users => users.FirstOrDefault(user => user.CustomEmoticons.Count > 0)))
                    foreach(IContact contact in contacts.GroupBy(x=>x.UserName).Where(x=>x is JiveContactModel && ((JiveContactModel)x).CustomEmoticons.Count>0))
                    {
                        if (contact != null && !ClientList.Contains(contact))
                            ClientList.Add(contact);
                    }
                }));
            


            if (ClientList.Count > 0)
                SelectedUser = ClientList.First();
        }

        private void CheckUncheckAllCommandAction(bool ischecked)
        {
            foreach (AddUserEmoticonModel model in this.EmoticonList)
            {
                model.IsChecked = ischecked;
            }

        }

        public override void Cleanup()
        {
            SimpleIoc.Default.Unregister<ViewModelGetUserEmoticons>(VmHelper.Locator.ViewModelGetUserEmoticonsKey);
            VmHelper.Locator.ViewModelGetUserEmoticonsKey = System.Guid.NewGuid().ToString();
            base.Cleanup();
        }

        private void ShortcutChangedCommandAction(AddUserEmoticonModel model)
        {
            string error;
            model.IsValidShortcut = _currentClient.ValidateEmoticonShortcut((string)model.EmoticonShortcut, out error);
            model.ErrorText = error;
        }
        private ObservableCollection<AddUserEmoticonModel> CreateEmoticonListForUser(string userID)
        {
            //EmoticonList.Clear();
            IsAddButtonEnabled = false;
            var emoticonList = new ObservableCollection<AddUserEmoticonModel>();
            var emoticons = _currentClient.GetEmoticons(userID, false, true, false);
            foreach (KeyValuePair<string, IEmoticon> kvp in emoticons)
            {
                try
                {
                    string error;
                    bool isValidShortcut = _currentClient.ValidateEmoticonShortcut(kvp.Key, out error);
                    bool emoticonExists = ValidateEmoticonExistsByHash(kvp.Value);
                    if (emoticonExists)
                        error = "You already have this emoticon image";

                    var model = new AddUserEmoticonModel()
                    {
                        EmoticonShortcut = kvp.Key,
                        EmoticonPath = kvp.Value.EmoticonPath,
                        IsValidShortcut = isValidShortcut,
                        EmoticonFileExists = emoticonExists,
                        ErrorText = error,
                        IsChecked = true
                    };

                    emoticonList.Add(model);
                }
                catch (Exception ex)
                {
                    Logger.ErrorException(ex.Message, ex);
                }
            }
            return emoticonList;
            //if (EmoticonList.Count > 0)
            //    IsAddButtonEnabled = true;
        }
        /// <summary>
        /// 
        /// </summary>
        private void AddEmoticonsCommandAction()
        {
            if (this.EmoticonList.Count == 0)
                return;
            int addedCount = 0;
            int errorCount = 0;
            foreach (AddUserEmoticonModel model in this.EmoticonList)
            {
                if (!model.IsValidShortcut || !model.IsChecked)
                    continue;
                try
                {
                    FileInfo sourceFile = new FileInfo(model.EmoticonPath);

                    Directory.CreateDirectory(ProgramSettings.Instance.CustomEmoticonFolder);
                    string hash = sourceFile.GetMD5();
                    //using (var md5 = MD5.Create())
                    //{
                    //    using (Stream stream = File.Open(sourceFile.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                    //    {
                    //        hash = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
                    //    }
                    //}

                    string savePath = StaticMethods.CombinePath(ProgramSettings.Instance.CustomEmoticonFolder, _currentClient.CurrentUserInfo.UserName, hash + sourceFile.Extension);// StaticMethods.CombinePath(ProgramSettings.Instance.CustomEmoticonFolder, _currentClient.CurrentUserInfo.UserName, sourceFile.Name);

                    sourceFile.CopyTo(savePath, true);
                    model.EmoticonPath = savePath;

                    ContactEmoticon ce = new ContactEmoticon()
                    {
                        Keyword = model.EmoticonShortcut,
                        Hash = hash,
                        Extension = sourceFile.Extension,
                        Index = this._currentClient.UserSettings.CustomEmoticons.Select(x => x.Index).OrderBy(n => n).LastOrDefault() + 1
                    };
                    this._currentClient.UserSettings.CustomEmoticons.Add(ce);
                    _currentClient.CurrentUserInfo.CustomEmoticons.Add(ce);

                    //string error;
                    //model.IsValidShortcut = _currentClient.ValidateEmoticonShortcut((string)model.EmoticonShortcut, out error);
                    //model.ErrorText = error;
                    addedCount++;
                }
                catch (Exception err)
                {
                    Logger.ErrorException("Error adding emoticon", err);
                    errorCount++;
                }
            }
            if (addedCount > 0 || errorCount > 0)
            {
                if (errorCount == 0)
                    Messenger.Default.Send(string.Format("Added {0} new emoticons", addedCount));
                else
                    Messenger.Default.Send(string.Format("Added {0} new emoticons. {1} emoticons could not be copied.", addedCount, errorCount));
            }

            if (addedCount > 0)
            {
                Messenger.Default.Send(new NotificationMessage(this, "UpdateCustomEmoticons"));
                PcUserSettings settings = new PcUserSettings();
                settings.CustomEmoticons = _currentClient.CurrentUserInfo.CustomEmoticons;
                _currentClient.Connection.SendCommand(settings, ClientCommands.PcSettings);

                foreach (var model in this.EmoticonList)
                {
                    ShortcutChangedCommand.Execute(model);
                }
            }
        }
        /// <summary>
        /// Checks if the hash of the emoticon matches any of the current clients emoticons
        /// </summary>
        /// <param name="emoticon"></param>
        /// <returns>Returns true if the user have the emoticon, else false</returns>
        private bool ValidateEmoticonExistsByHash(IEmoticon emoticon)
        {
            try
            {
                string hash = new FileInfo(emoticon.EmoticonPath).GetMD5();
                if (this._currentClient.CurrentUserInfo.CustomEmoticons.Any(x => x.Hash == hash))
                    return true;
                else
                    return false;
                //using (Stream stream = File.Open(emoticon.EmoticonPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                //{
                //    using (MD5 md5 = MD5.Create())
                //    {
                //        var hash = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
                //        stream.Close();
                //        if (this._currentClient.CurrentUserInfo.CustomEmoticons.Any(x => x.Hash == hash))
                //            return true;
                //        else
                //            return false;
                //    }
                //}

            }
            catch (Exception ex)
            {
                Logger.ErrorException("Error checking if emoticon file exists by hash", ex);
                throw;
            }
        }
    }
}